package code.example.base.reflect.classz;

import code.example.base.reflect.BikeProducer;
import code.example.base.reflect.GenerateHuman;
import code.example.base.reflect.Human;
import code.example.tool.LogFactory;
import org.springframework.core.ParameterizedTypeReference;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class TestClass {

    public void isType(Object obj ){
        Class classz = obj.getClass();
        boolean flag = GenerateHuman.class.isInstance(obj);
        LogFactory.getLog().info("GenerateHuman.class.isInstance("+classz.getCanonicalName()+"):"+flag);
        flag = Human.class.isAssignableFrom(classz);
        LogFactory.getLog().info("Human.class.isAssignableFrom("+classz.getCanonicalName()+"):"+flag);
        flag =  classz.isAnnotation();
        LogFactory.getLog().info(classz.getCanonicalName()+" classz.isAnnotation():"+flag);
        flag =   classz.isArray();
        LogFactory.getLog().info(classz.getCanonicalName()+" classz.isArray():"+flag);
        flag = classz.isEnum();
        LogFactory.getLog().info(classz.getCanonicalName()+" classz.isEnum():"+flag);
        flag = classz.isInterface();
        LogFactory.getLog().info(classz.getCanonicalName()+" classz.isInterface():"+flag);

    }
    public void showSuperInterface(Class classz){

        Type [] types  = classz.getGenericInterfaces();
        if(types != null && types.length>0){
            LogFactory.getLog().info("----------------show interface -----------------------");
            for(Type type :types){
                showType(type);
            }
            LogFactory.getLog().info("----------------show interface -----------------------");
        }

    }
    public void printSuperClass(Object obj ){
        Class classz = obj.getClass();

        LogFactory.getLog().info("----------------show parent class -----------------------");
        showParentClass(classz);
        LogFactory.getLog().info("----------------show parent class -----------------------");
    }
    public void showParentClass(Class classz ){
        if(Object.class.equals(classz)) {
            return;
        }
        Type type = classz.getGenericSuperclass();

        showType(type);

    }
    public void showType(Type type){
        if(type == null){

        }else  if(ParameterizedType.class.isAssignableFrom(type.getClass())){
            ParameterizedType parameterizedType = (ParameterizedType) type;
            String typeName = type.getTypeName();
            LogFactory.getLog().info("ParameterizedType:"+typeName);
            Type[] types = parameterizedType.getActualTypeArguments();
            for(Type param:types){
                showType(param);
            }
            Type rawType =  parameterizedType.getRawType();
            showType(rawType);
        }else if(Class.class.isAssignableFrom(type.getClass())){
                 Class classz = (Class)type;
                 if(Object.class.equals(classz)){
                    return;
                }
                String name =  classz.getCanonicalName();
                LogFactory.getLog().info("className:"+name);
                showParentClass(classz);
                showSuperInterface(classz);
        }else if(TypeVariable.class.isAssignableFrom(type.getClass())){
            TypeVariable typeVariable = (TypeVariable)type;
            String name = typeVariable.getName();
            LogFactory.getLog().info("type:"+name);
        }
    }

    public void printClassName( Object obj ){
        Class classz = obj.getClass();
        String canonicalName = classz.getCanonicalName();
        LogFactory.getLog().info("class.canonicalName="+canonicalName);
        String simpleName = classz.getSimpleName();
        LogFactory.getLog().info("class.simpleName="+simpleName);
        String name = classz.getName();
        LogFactory.getLog().info("class.name="+name);
        String typeName = classz.getTypeName();
        LogFactory.getLog().info("class.typeName="+typeName);
    }
    public Object generate(){
        BikeProducer bikeProducer = new BikeProducer();
        bikeProducer.setCompanyName("大灯车厂");
        bikeProducer.setName("张三");
        return bikeProducer;
    }
    public void test(){
        Object obj = generate();
        printClassName(obj);
        printSuperClass(obj);
        isType(obj);
    }
    public static void main(String args []){
        new TestClass().test();
    }
}
